//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "ShipmentBridge.h"
#include "StringUtilities.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

TShipment :: TShipment()
{
   provider = new TProvider();
}

TShipment :: TShipment( TShipment* other)
{
   number       = other->number;
   shipmentDate = other->shipmentDate;
   amount       = other->amount;
   provider     = new TProvider(other->provider);
}

__fastcall TShipment :: ~TShipment()
{
   delete provider;
}

bool TShipment :: IsEqual( TShipment* other)
{
   return (( number == other->number) && ( shipmentDate == other->shipmentDate));
}

AnsiString TShipment :: GetKey()
{
   return IntToStr(number) + "_" + DateToStr( shipmentDate);        
}

//-------------------------- Shipment Bridge ----------------------------------

TShipmentBridge :: TShipmentBridge( TDatabase * database)
{
   qryExists = new TQuery( NULL);
   qryExists->DatabaseName = database->DatabaseName;
   BuildExistsQuery();

   qryGet = new TQuery( NULL);
   qryGet->DatabaseName = database->DatabaseName;
   BuildGetQuery();

   qryAdd = new TQuery( NULL);
   qryAdd->DatabaseName = database->DatabaseName;
   BuildAddQuery();

   qryUpdate = new TQuery( NULL);
   qryUpdate->DatabaseName = database->DatabaseName;
   BuildUpdateQuery();

   qryDelete = new TQuery( NULL);
   qryDelete->DatabaseName = database->DatabaseName;
   BuildDeleteQuery();

   qryGetShipments = new TQuery( NULL);
   qryGetShipments->DatabaseName = database->DatabaseName;
   BuildGetShipmentsQuery();

   qryGetDetails = new TQuery( NULL);
   qryGetDetails->DatabaseName = database->DatabaseName;

   qryAddDetails = new TQuery( NULL);
   qryAddDetails->DatabaseName = database->DatabaseName;

   qryDeleteDetails = new TQuery( NULL);
   qryDeleteDetails->DatabaseName = database->DatabaseName;

   qrySetDetails = new TQuery( NULL);
   qrySetDetails->DatabaseName = database->DatabaseName;
}

TShipmentBridge :: ~TShipmentBridge()
{
   delete qryGetShipments;
   delete qryDelete;
   delete qryAdd;
   delete qryGet;
   delete qryExists;
   delete qryGetDetails;
   delete qryAddDetails;
   delete qryDeleteDetails;
}

void TShipmentBridge :: BuildExistsQuery()
{
   qryExists->SQL->Add( "SELECT * FROM SHIPMENTS");
   qryExists->SQL->Add( "WHERE ( SHIPMENT_NUMBER = :prmShipmentNo) AND ( SHIPMENT_DATE = :prmShipmentDate)");
}

void TShipmentBridge :: BuildGetQuery()
{
   qryGet->SQL->Add( "SELECT * FROM SHIPMENTS, PROVIDERS");
   qryGet->SQL->Add( "WHERE SHIPMENTS.PROVIDER_ID = PROVIDERS.ID");
   qryGet->SQL->Add( "WHERE ( SHIPMENT_NUMBER = :prmShipmentNo) AND ( SHIPMENT_DATE = :prmShipmentDate)");
}

void TShipmentBridge :: BuildAddQuery()
{
   qryAdd->SQL->Add( "INSERT INTO SHIPMENTS VALUES ( :prmShipmentNo, :prmShipmentDate, :prmAmount, :prmProviderID)");
}

void TShipmentBridge :: BuildUpdateQuery()
{
   qryUpdate->SQL->Add( "UPDATE SHIPMENTS");
   qryUpdate->SQL->Add( "SET SHIPMENT_NUMBER = :prmNewShipmentNo,");
   qryUpdate->SQL->Add( "SHIPMENT_DATE = :prmNewShipmentDate,");
   qryUpdate->SQL->Add( "AMOUNT = :prmNewAmount,");
   qryUpdate->SQL->Add( "PROVIDER_ID = :prmNewProviderID");   
   qryUpdate->SQL->Add( "WHERE");
   qryUpdate->SQL->Add( "(SHIPMENT_NUMBER = :prmOldShipmentNo) AND");
   qryUpdate->SQL->Add( "(SHIPMENT_DATE = :prmOldShipmentDate)");
}

void TShipmentBridge :: BuildDeleteQuery()
{
   qryDelete->SQL->Add( "DELETE FROM SHIPMENTS WHERE");
   qryDelete->SQL->Add( "( SHIPMENT_NUMBER = :prmShipmentNo) AND ( SHIPMENT_DATE = :prmShipmentDate)");
}

void TShipmentBridge :: BuildGetShipmentsQuery()
{
   qryGetShipments->SQL->Add( "SELECT * FROM SHIPMENTS, PROVIDERS");
   qryGetShipments->SQL->Add( "WHERE SHIPMENTS.PROVIDER_ID = PROVIDERS.ID");     
   qryGetShipments->SQL->Add( "ORDER BY SHIPMENT_DATE DESC, SHIPMENT_NUMBER DESC");
}

void SetShipment( TQuery* query, TShipment* shipment)
{
   shipment->number         = query->FieldByName( "SHIPMENT_NUMBER")->AsInteger;
   shipment->shipmentDate   = query->FieldByName( "SHIPMENT_DATE")->AsDateTime;
   shipment->amount         = ( double)query->FieldByName( "AMOUNT")->AsCurrency;
   shipment->provider->id   = query->FieldByName( "PROVIDER_ID")->AsInteger;
   shipment->provider->name = query->FieldByName( "NAME")->AsString;
}

bool TShipmentBridge :: IsExist( int number, TDateTime shipmentDate)
{
   bool result = false;

   qryExists->ParamByName( "prmShipmentNo")->AsInteger   = number;
   qryExists->ParamByName( "prmShipmentDate")->AsDateTime = shipmentDate;

   qryExists->Open();

   try
   {
      result = ( !qryExists->IsEmpty());
   }
   __finally
   {
      qryExists->Close();
   }//try-finally

   return result;
}

void TShipmentBridge :: Get( int number, TDateTime shipmentDate, TShipment* shipment)
{
   qryGet->ParamByName( "prmShipmentNo")->AsInteger    = number;
   qryGet->ParamByName( "prmShipmentDate")->AsDateTime = shipmentDate;

   qryGet->Open();

   try
   {
      SetShipment( qryGet, shipment);
   }
   __finally
   {
      qryGet->Close();
   }
}

void TShipmentBridge :: GetShipments( TStrings * shipments)
{
   TShipment * shipment;
   
   qryGetShipments->Open();

   try
   {
      TStringUtilites :: Clear( shipments);

      qryGetShipments->First();

      while ( !qryGetShipments->Eof)
      {
         shipment = new TShipment();
         SetShipment( qryGetShipments, shipment);
         shipments->AddObject( shipment->GetKey(), shipment);
         qryGetShipments->Next();
      }
   }
   __finally
   {
      qryGetShipments->Close();
   }
}

void TShipmentBridge :: Add( TShipment* shipment)
{
   qryAdd->ParamByName( "prmShipmentNo")->AsInteger = shipment->number;
   qryAdd->ParamByName( "prmShipmentDate")->AsDateTime = shipment->shipmentDate;
   qryAdd->ParamByName( "prmAmount")->AsCurrency = shipment->amount;
   qryAdd->ParamByName( "prmProviderID")->AsInteger = shipment->provider->id;

   qryAdd->ExecSQL();
}

void TShipmentBridge :: Update( TShipment* oldShipment, TShipment* newShipment)
{
   qryUpdate->ParamByName( "prmNewShipmentNo")->AsInteger = newShipment->number;
   qryUpdate->ParamByName( "prmNewShipmentDate")->AsDateTime = newShipment->shipmentDate;
   qryUpdate->ParamByName( "prmNewAmount")->AsCurrency = newShipment->amount;
   qryUpdate->ParamByName( "prmNewProviderID")->AsInteger = newShipment->provider->id;
   qryUpdate->ParamByName( "prmOldShipmentNo")->AsInteger = oldShipment->number;
   qryUpdate->ParamByName( "prmOldShipmentDate")->AsDateTime = oldShipment->shipmentDate;

   qryUpdate->ExecSQL();
}

void TShipmentBridge :: Delete( int number, TDateTime shipmentDate)
{
   qryDelete->ParamByName( "prmShipmentNo")->AsInteger   = number;
   qryDelete->ParamByName( "prmShipmentDate")->AsDateTime = shipmentDate;
   qryDelete->ExecSQL();
}

void SetDetails( TQuery* query, TShipmentDetails* sd)
{
   sd->id   = query->FieldByName( "ID")->AsInteger;
   sd->shipmentNo = query->FieldByName( "SHIPMENT_NO")->AsInteger;
   sd->firm = query->FieldByName( "FIRM")->AsString;
   sd->model = query->FieldByName( "MODEL")->AsString;
   sd->amount = query->FieldByName( "AMOUNT")->AsInteger;
}

void TShipmentBridge :: GetDetails(__int64 shipmentNo, TStrings * details)
{
   qryGetDetails->SQL->Clear();

   qryGetDetails->SQL->Add( "SELECT * FROM SHIPMENTDETAILS");
   qryGetDetails->SQL->Add( "WHERE SHIPMENT_NO = :prmShipmentNo");

   qryGetDetails->ParamByName("prmShipmentNo")->AsInteger = shipmentNo;
   qryGetDetails->Open();

   TShipmentDetails * sd;

   try
   {
      TStringUtilites :: Clear( details);

      qryGetDetails->First();

      while ( !qryGetDetails->Eof)
      {
         sd = new TShipmentDetails();
         SetDetails( qryGetDetails, sd);

         details->AddObject( IntToStr(sd->id), sd);
         qryGetDetails->Next();
      }
   }
   __finally
   {
      qryGetDetails->Close();
   }
}

void TShipmentBridge :: AddDetails(TShipmentDetails * sd)
{
   qryAddDetails->SQL->Clear();

   qryAddDetails->SQL->Add( "INSERT INTO SHIPMENTDETAILS (SHIPMENT_NO, FIRM, MODEL, AMOUNT) VALUES ( :prmShipmentNo, :prmFirm, :prmModel, :prmAmount)");

   qryAddDetails->ParamByName("prmShipmentNo")->AsInteger = sd->shipmentNo;
   qryAddDetails->ParamByName("prmFirm")->AsString = sd->firm;
   qryAddDetails->ParamByName("prmModel")->AsString = sd->model;
   qryAddDetails->ParamByName("prmAmount")->AsInteger = sd->amount;

   try
   {
      qryAddDetails->ExecSQL();
   }
   __finally
   {
      qryAddDetails->Close();
   }
}

void TShipmentBridge :: DeleteDetails(__int64 id)
{
   qryDeleteDetails->SQL->Clear();

   qryDeleteDetails->SQL->Add( "DELETE FROM SHIPMENTDETAILS");
   qryDeleteDetails->SQL->Add( "WHERE ID = :prmID");

   qryDeleteDetails->ParamByName("prmID")->AsInteger = id;

   try
   {
      qryDeleteDetails->ExecSQL();
   }
   __finally
   {
      qryDeleteDetails->Close();
   }
}

void TShipmentBridge :: UpdateDetails(__int64 shipmentNo, TStrings * details)
{
   qryDeleteDetails->SQL->Clear();

   qryDeleteDetails->SQL->Add( "DELETE FROM SHIPMENTDETAILS");
   qryDeleteDetails->SQL->Add( "WHERE SHIPMENT_NO = :prmShipmentNo");

   qryDeleteDetails->ParamByName("prmShipmentNo")->AsInteger = shipmentNo;

   try
   {
      qryDeleteDetails->ExecSQL();
   }
   __finally
   {
      qryDeleteDetails->Close();
   }

   for (int i = 0; i < details->Count; ++i)
   {
      TShipmentDetails * sd = (TShipmentDetails*)details->Objects[i];

      AddDetails( sd);       
   }
}
